package algorithm1_v3;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class Task2 implements Callable<Object> {

	static Logger logger = LoggerFactory.getLogger(Task2.class);

	@Override
	public Object call() throws Exception {
		DatagramSocket socket = new DatagramSocket(12345);
		byte[] buf = new byte[1024];
		DatagramPacket packet = new DatagramPacket(buf, buf.length);
		SystemInfo info = SystemInfo.INSTANCE;
		String machineName = InetAddress.getLocalHost().getHostName();
		ScheduledExecutorService task3 = Executors
				.newSingleThreadScheduledExecutor();
		ScheduledFuture<String> task3Future = null;
		if (info.leader.toString().compareTo(machineName) != 0) {
			task3Future = task3.schedule(new Task3(),
					info.timeout.get(info.leader.toString()),
					TimeUnit.MILLISECONDS);
		}
		while (true) {
			try {
				socket.receive(packet);
				ByteArrayInputStream bais = new ByteArrayInputStream(buf);
			    ObjectInputStream ois = new ObjectInputStream(bais);
				//logger.info("Mezuaren zain");
				Message message = (Message) ois.readObject();
				logger.info("Mezua jasota: " + message.process.toString());
				for (String entry : message.recovered.keySet()) {
					try{
					info.recovered.put(entry, Math.max(
							info.recovered.get(entry),
							message.recovered.get(entry)));
					}catch(Exception e){
						e.printStackTrace();
					}
				}
				if (info.recovered.get(message.process.toString()) <= info.recovered
						.get(info.leader.toString())) {
					info.leader.replace(0, info.leader.length(),
							message.process.toString());
					logger.info("leader berria recovered obea: " + info.leader.toString());
					//logger.info("3. Ataza Gelditu");
					if (task3Future != null) {
						task3Future.cancel(false);
					}
					task3.shutdown();
					task3 = Executors.newSingleThreadScheduledExecutor();
					//logger.info("3. Ataza Martxan");
					try{
					task3Future = task3.schedule(new Task3(),
							info.timeout.get(info.leader.toString()),
							TimeUnit.MILLISECONDS);
					}catch(Exception e){
						e.printStackTrace();
					}
				}
				if (info.recovered.get(machineName) < info.recovered
						.get(info.leader.toString())) {
					info.leader.replace(0, info.leader.length(), machineName);
					//logger.info("3. Ataza geldituta");
					task3Future.cancel(false);
					task3.shutdown();
				}
				

			} catch (Exception e) {
				logger.info("ERROREA: Task2 mezua jasotzean");
				e.printStackTrace();
			} finally {
				try {
					socket.close();
				} catch (Exception e) {
					logger.info("ERROREA: Task2 socketa ixtean");
					e.printStackTrace();
				}
			}
		}
	}
}
